package com.ecarx.vhaltests.hy11.testcases.system.seatadjustment;

import static android.car.VehiclePropertyIds.SEAT_FORE_AFT_MOVE;

import android.car.VehicleAreaSeat;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

//HY11 [SW_FC_004_043]第一排座椅滑移1stRowSeatLengthAdjustment
public class SeatForeAftMoveTest extends VhalUnitTestBase {
    public static final String TAG = "SEAT_FORE_AFT_MOVE";
    private static int halValueRow1Left;
    private static int halStatusRow1Left;
    private static int halValueRow1Right;
    private static int halStatusRow1Right;
    final static Object lockRow1Left = new Object();
    final static Object lockRow1Right = new Object();

    private static final int SEAT_SlD_OFF = 0;
    private static final int SEAT_SLD_FORWARD = 1;
    private static final int SEAT_SlD_BACKWARD = 2;
    private static final int PARAM_INVALID = 6;

    private static final IpcpClient ipcpClient = new IpcpClient();

    @BeforeClass
    public static void testInit() {
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, SEAT_FORE_AFT_MOVE, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig();
    }

    @Test
    public void testSeatForeAftMoveNotAvail() {
        setSeatForeAftMoveNotAvail();
        lockRow1Left();
        lockRow1Right();
        Assert.assertEquals(halStatusRow1Left, 1);
        Assert.assertEquals(halStatusRow1Right, 1);
        testSeatForeAftMoveNotAvailLeft();
        testSeatForeAftMoveNotAvailRight();
    }

    @Test
    public void testSeatForeAftMoveAvail() {
        setSeatForeAftMoveAvail();
        lockRow1Left();
        lockRow1Right();
        Assert.assertEquals(halStatusRow1Left, 0);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveIsAvailLeft();
        testSeatForeAftMoveIsAvailRight();
    }

    @Test
    public void testSeatForeAftMoveBtnPress() {//硬按键按下
        setSeatForeAftMoveAvail();
        setCDM(1, 1, 0, 1, 1, 0);//硬按键按下
        lockRow1Left();
        lockRow1Right();
        Assert.assertEquals(halStatusRow1Left, 1);
        Assert.assertEquals(halStatusRow1Right, 1);
        testSeatForeAftMoveNotAvailLeft();
        testSeatForeAftMoveNotAvailRight();
    }

    @Test
    public void testSeatForeAftMoveRow1LeftGearLvrIndcnNotP() {//主驾GearLvrIndcn！=P
        setSeatForeAftMoveAvail();
        setVDDM(1);
        lockRow1Left();
        Assert.assertEquals(halStatusRow1Left, 1);
        testSeatForeAftMoveNotAvailLeft();
    }


    @Test
    public void testSeatForeAftMoveRow1LeftForward() {//正常向前,移动中
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SLD_FORWARD);
        setCDMDriver(60, 0, 1);//当前百分比60%，硬按键未按下，座椅前后正在向前调整
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SLD_FORWARD);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SLD_FORWARD);
    }

    @Test
    public void testSeatForeAftMoveRow1LeftForwardStop() {//正常向前后到最大停止
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SLD_FORWARD);
        setCDMDriver(100, 0, 1);//当前百分比100%，硬按键未按下，座椅前后正在向前调整
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);//停止向前打开
    }

    @Test
    public void testSeatForeAftMoveRow1LeftForwardCannotMove() {//已经无法再向前，再设置向前
        setSeatForeAftMoveAvail();
        setCDMDriver(100, 0, 0);//当前百分比100%，硬按键未按下，座椅前后无移动
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SLD_FORWARD);
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);
    }

    @Test
    public void testSeatForeAftMoveRow1LeftBackward() {//正常向后中
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_BACKWARD);
        setCDMDriver(40, 0, 2);//当前百分比40%，硬按键未按下，座椅前后正在向后调整
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_BACKWARD);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_BACKWARD);
    }


    @Test
    public void testSeatForeAftMoveRow1LeftBackwardStop() {//正常向后后到最小停止
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_BACKWARD);
        setCDMDriver(0, 0, 2);//当前百分比40%，硬按键未按下，座椅前后正在向后调整
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);//停止向后
    }


    @Test
    public void testSeatForeAftMoveRow1LeftBackwardCannotMove() {//已经无法再向后，再设置向后
        setSeatForeAftMoveAvail();
        setCDMDriver(0, 0, 0);//当前百分比0%，硬按键未按下，座椅前后正在向后调整
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_BACKWARD);
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);
    }

    @Test
    public void testSeatForeAftMoveRow1LeftOff() {
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);
        setCDMDriver(50, 0, 0);//当前百分比50%，硬按键未按下，座椅前后无移动
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);
    }

    @Test
    public void testSeatForeAftMoveRow1LeftParamInvalid() {
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);

        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, PARAM_INVALID);
        lockRow1Left();
        Assert.assertEquals(halValueRow1Left, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Left, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_LEFT, SEAT_SlD_OFF);
    }


    @Test
    public void testSeatForeAftMoveRow1RightForward() {//正常向前中
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SLD_FORWARD);
        setCDMPass(60, 0, 1);//当前百分比60%，硬按键未按下，座椅前后正在向前调整
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SLD_FORWARD);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SLD_FORWARD);
    }

    @Test
    public void testSeatForeAftMoveRow1RightForwardStop() {//正常向前后到最大停止
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SLD_FORWARD);
        setCDMPass(100, 0, 1);//当前百分比100%，硬按键未按下，座椅前后正在向前调整
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);//停止向前打开
    }

    @Test
    public void testSeatForeAftMoveRow1RightForwardCannotMove() {//已经无法再向前，再设置向前
        setSeatForeAftMoveAvail();
        setCDMPass(100, 0, 0);//当前百分比100%，硬按键未按下，座椅前后无移动
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SLD_FORWARD);
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);
    }

    @Test
    public void testSeatForeAftMoveRow1RightBackward() {//正常向后中
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_BACKWARD);
        setCDMPass(40, 0, 2);//当前百分比40%，硬按键未按下，座椅前后正在向后调整
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_BACKWARD);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_BACKWARD);
    }


    @Test
    public void testSeatForeAftMoveRow1RightBackwardStop() {//正常向后后到最小停止
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_BACKWARD);
        setCDMPass(0, 0, 2);//当前百分比40%，硬按键未按下，座椅前后正在向后调整
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);//停止向后
    }


    @Test
    public void testSeatForeAftMoveRow1RightBackwardCannotMove() {//已经无法再向后，再设置向后
        setSeatForeAftMoveAvail();
        setCDMPass(0, 0, 0);//当前百分比0%，硬按键未按下，座椅前后正在向后调整
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_BACKWARD);
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);
    }

    @Test
    public void testSeatForeAftMoveRow1RightOff() {
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);
        setCDMPass(50, 0, 0);//当前百分比50%，硬按键未按下，座椅前后无移动
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);
    }

    @Test
    public void testSeatForeAftMoveRow1RightParamInvalid() {
        setSeatForeAftMoveAvail();
        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);

        setSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, PARAM_INVALID);
        lockRow1Right();
        Assert.assertEquals(halValueRow1Right, SEAT_SlD_OFF);
        Assert.assertEquals(halStatusRow1Right, 0);
        testSeatForeAftMoveValue(VehicleAreaSeat.SEAT_ROW_1_RIGHT, SEAT_SlD_OFF);
    }


    public void setSeatForeAftMoveValue(int areaId, int value) {
        mCarPropertyMgr.setIntProperty(SEAT_FORE_AFT_MOVE, areaId, value);
    }

    public void testSeatForeAftMoveValue(int areaId, int value) {
        int halValue = mCarPropertyMgr.getIntProperty(SEAT_FORE_AFT_MOVE, areaId);
        Assert.assertEquals(halValue, value);
    }

    public void testSeatForeAftMoveIsAvailLeft() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_FORE_AFT_MOVE, VehicleAreaSeat.SEAT_ROW_1_LEFT);
        Assert.assertTrue(isAvail);
    }

    public void testSeatForeAftMoveIsAvailRight() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_FORE_AFT_MOVE, VehicleAreaSeat.SEAT_ROW_1_RIGHT);
        Assert.assertTrue(isAvail);
    }

    public void testSeatForeAftMoveNotAvailLeft() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_FORE_AFT_MOVE, VehicleAreaSeat.SEAT_ROW_1_LEFT);
        Assert.assertFalse(isAvail);
    }

    public void testSeatForeAftMoveNotAvailRight() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_FORE_AFT_MOVE, VehicleAreaSeat.SEAT_ROW_1_RIGHT);
        Assert.assertFalse(isAvail);
    }

    public void lockRow1Left() {
        try {
            synchronized (lockRow1Left) {
                lockRow1Left.wait(1000);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void lockRow1Right() {
        try {
            synchronized (lockRow1Right) {
                lockRow1Right.wait(1000);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            try {
                Log.d(TAG, carPropertyValue.toString());

                int areaId = carPropertyValue.getAreaId();
                if (areaId == VehicleAreaSeat.SEAT_ROW_1_LEFT) {
                    halValueRow1Left = (int) carPropertyValue.getValue();
                    halStatusRow1Left = carPropertyValue.getStatus();
                    synchronized (lockRow1Left) {
                        lockRow1Left.notify();
                    }
                } else if (areaId == VehicleAreaSeat.SEAT_ROW_1_RIGHT) {
                    halValueRow1Right = (int) carPropertyValue.getValue();
                    halStatusRow1Right = carPropertyValue.getStatus();
                    synchronized (lockRow1Right) {
                        lockRow1Right.notify();
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };

    private static void setConfig() {
        int cemSvcId = 37;
        int[] cemOperIds = {999};
        int ccSvcId = 135;
        int[] ccOperIds = {200};
        int cc1000SvcId = 136;
        int[] cc1000OperIds = {200};
        int cdmSvcId = 36;
        int[] cdmOperIds = {999};
        int vddmSvcId = 48;
        int[] vddmOperIds = {999};

        boolean retCem = ipcpClient.setConfig(cemSvcId, cemOperIds);
        Assert.assertTrue(retCem);

        boolean retCc = ipcpClient.setConfig(ccSvcId, ccOperIds);
        Assert.assertTrue(retCc);

        boolean retCdm = ipcpClient.setConfig(cdmSvcId, cdmOperIds);
        Assert.assertTrue(retCdm);

        boolean retCc1000 = ipcpClient.setConfig(cc1000SvcId, cc1000OperIds);
        Assert.assertTrue(retCc1000);

        boolean retVddm = ipcpClient.setConfig(vddmSvcId, vddmOperIds);
        Assert.assertTrue(retVddm);
    }

    public void setSeatForeAftMoveNotAvail() {
        setCarConfig(5);
        setCarConfig1000(3, 6);
        setCEM(VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_ABANDON);
    }


    public void setSeatForeAftMoveAvail() {
        setCarConfig(2);
        setCarConfig1000(2, 2);
        setVDDM(0);
        setCDM(50, 0, 0, 50, 0, 0);
        setCEM(VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_DRIVING);
    }

    public void setCEM(int carMode, int usgMode) {
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"};
        int[] cemValues = {carMode, usgMode};
        boolean cemResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        Assert.assertTrue(cemResult);
        delay();
    }

    public void setCarConfig(int cc472) {
        int ccSvcId = 135;
        int ccOperId = 200;
        int[] configs = {472};
        int[] values = {cc472};
        boolean ccResult = ipcpClient.setCarconfigSignal(ccSvcId, ccOperId, configs, values);
        Assert.assertTrue(ccResult);
        delay();
    }

    private void setCarConfig1000(int cc1173, int cc1174) {
        int ccSvcId = 136;
        int ccOperId = 200;
        int[] configs = {1173, 1174};
        int[] values = {cc1173, cc1174};
        boolean ccResult = ipcpClient.setCarconfig1000Signal(ccSvcId, ccOperId, configs, values);
        Assert.assertTrue(ccResult);
        delay();
    }

    private void setVDDM(int gearLvrIndcn) {
        int svcId = 48;
        int operId = 999;
        String[] vddms = {"gearLvrIndcn"};
        int[] values = {gearLvrIndcn};
        boolean toRet = ipcpClient.setVDDMSignal(svcId, operId, vddms, values);
        Assert.assertTrue(toRet);
        delay();
    }

    public void setCDMDriver(int drvrSeatPosPercSeatPosSldPerc, int drvrSeatBtnPsd, int drvrSeatSwtStsDrvrSeatSwtSldSts) {
        setCDM(drvrSeatPosPercSeatPosSldPerc, drvrSeatBtnPsd, drvrSeatSwtStsDrvrSeatSwtSldSts, 0, 0, 0);
    }

    public void setCDMPass(int passSeatPosPercSeatPosSldPerc, int passSeatBtnPsd, int passSeatSwtSts2PassSeatSwtSldSts) {
        setCDM(0, 0, 0, passSeatPosPercSeatPosSldPerc, passSeatBtnPsd, passSeatSwtSts2PassSeatSwtSldSts);
    }

    public void setCDM(int drvrSeatPosPercSeatPosSldPerc, int drvrSeatBtnPsd, int drvrSeatSwtStsDrvrSeatSwtSldSts, int passSeatPosPercSeatPosSldPerc, int passSeatBtnPsd, int passSeatSwtSts2PassSeatSwtSldSts) {
        int cdmSvcId = 36;
        int cdmOperId = 999;
        String[] cdms = {"drvrSeatExtAdjAllowd", "drvrSeatPosPercSeatPosSldPerc", "drvrSeatBtnPsd", "drvrSeatSwtStsDrvrSeatSwtSldSts", "drvrSeatPosPercSeatPosSldQF", "passSeatPosPercSeatPosSldPerc", "passSeatBtnPsd", "passSeatSwtSts2PassSeatSwtSldSts", "passSeatPosPercSeatPosSldQF"};
        int[] cdmValues = {1, drvrSeatPosPercSeatPosSldPerc * 10, drvrSeatBtnPsd, drvrSeatSwtStsDrvrSeatSwtSldSts, 3, passSeatPosPercSeatPosSldPerc * 10, passSeatBtnPsd, passSeatSwtSts2PassSeatSwtSldSts, 3};
        boolean cdmResult = ipcpClient.setCDMSignal(cdmSvcId, cdmOperId, cdms, cdmValues);
        Assert.assertTrue(cdmResult);
        delay();
    }

}